package com.example.app;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.calibur.engine.Event;
import net.sf.calibur.engine.task.Handler;
import net.sf.calibur.engine.task.TaskInstance;
import net.sf.calibur.msgbuf.MessageBean;
import net.sf.calibur.transport.CommandMessageEvent;
import net.sf.calibur.transport.Session;

import com.example.app.messagebean.CommandResponse;

import static net.sf.calibur.i18n.R.*;

public class CommandHandler extends Handler {
	private final static int ERROR_SYSTEM = 999;
	protected Logger logger = LoggerFactory.getLogger(getClass());

	public CommandHandler(String name) {
		super(name);
	}

	protected Player getBindPlayer(Session session) {
		return (Player) session.getAttribute(AppContext.ATTR_PLAYER);
	}

	@Override
	public void executeTask(TaskInstance taskInstance) {
		try {
			taskInstance.getTask().execute(taskInstance.getEvent());
		} catch (Exception e) {
			// TODO: 客户端指令处理的公共异常的处理放在这里，例如UserOperationException。
			// UserOperationException中包含：
			// 1. commandId，用哪个commandId及其对应的MessageBean给客户端发响应。
			// 如果commandId正负值表示请求和响应，则可以直接从event中获得commandId，取负值即可。
			// 2. errorCode 0表示无错误
			// 3. errorMessage 显示给用户的错误提示消息
			// 所有这类的MessageBean必须有errorCode和errorMessage字段。或者包含一个统一的Error
			// MessageBean。
			// ！！！不要滥用Push0
			logger.error(_("指令处理错误"), e);
			sendErrorResponse(taskInstance.getEvent(), e);
		}
	}

	private void sendErrorResponse(Event event, Exception exception) {
		CommandResponse cr = null;
		int errorCode;
		String errorMessage;

		if (exception instanceof UserOperationException) {
			UserOperationException uoe = (UserOperationException) exception;
			errorCode = uoe.getErrorCode();
			errorMessage = uoe.getMessage();
		} else {
			errorCode = ERROR_SYSTEM;
			errorMessage = _("系统繁忙，请稍后重试。");
		}

		try {
			CommandMessageEvent cme = (CommandMessageEvent) event;
			cr = (CommandResponse) cme.getOutput();
			cr.setErrorCode(errorCode);
			cr.setErrorMessage(errorMessage);
			cme.sendResponse();
		} catch (Exception e) {
			logger.error(_("发送错误信息到客户端失败。"), e);
		}
	}

	public <T extends MessageBean> T getMessageBean(Class<T> clazz) {
		return AppContext.getInstance().getHandlerContext()
				.getMessageBean(clazz);
	}

	@Override
	public void prepareExecute(TaskInstance taskInstance) {
	}

	@Override
	public void postExecute(TaskInstance taskInstance) {
		try {
			AppContext ctx = AppContext.getInstance();
			// 释放event上携带的input/output MessageBean
			taskInstance.getEvent().release();

			ctx.getHandlerContext().clear();
			if (logger.isDebugEnabled()) {
				logger.info(ctx.getMessageBeanFactory().getMessageBeanPool()
						.toString());
			}
		} catch (Throwable t) {
			logger.error("clear executor " + getName() + " error.", t);
		}
	}
}
